package net.orange.framework.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import net.orange.architecture.model.BaseValueObject;
import net.orange.architecture.validator.NotDulicateValidator;
import net.orange.architecture.validator.ObjectNotNullValidator;
import net.orange.architecture.validator.SetNotNullValidator;
import net.orange.architecture.validator.StringNotNullValidator;
import net.orange.architecture.validator.Validator;
import net.orange.framework.validator.UserCodeFormatValidator;

/**
 * The system user, it special by unique account & self-define password. it must
 * define the special department and groups.
 */
@Entity
@Table(name = "t_user")
public class User extends BaseValueObject {

	private static final long serialVersionUID = -4036703711340171521L;

	/**
	 * The user code.
	 */
	@Column(name = "user_code")
	private String user_code;

	/**
	 * The user name
	 */
	@Column(name = "user_name")
	private String user_name;

	/**
	 * The user login account
	 */
	@Column(name = "login_no")
	private String login_no;

	/**
	 * The user login password.
	 */
	@Column(name = "login_pwd")
	private String login_pwd;

	/**
	 * The user's email address
	 */
	@Column(name = "email")
	private String email;

	/**
	 * The user phone number
	 */
	@Column(name = "phone")
	private String phone;

	/**
	 * The user mobile number
	 */
	@Column(name = "mobile")
	private String mobile;

	/**
	 * The user fax numebr
	 */
	@Column(name = "fax")
	private String fax;

	/**
	 * The user address
	 */
	@Column(name = "address")
	private String address;

	/**
	 * The user department
	 */
	@ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.EAGER)
	@JoinColumn(name = "dept_pk", insertable = true, updatable = true)
	private Department department;

	/**
	 * Whether the user is blocked to login
	 */
	@Column(name = "isstop")
	private boolean isstop;

	/**
	 * The user's home page which is defined in common info object.
	 */
	@Column(name = "homepage")
	private String homepage;

	/**
	 * The description
	 */
	@Column(name = "description")
	private String description;

	/**
	 * The groups user assign to .
	 */
	@ManyToMany(targetEntity = net.orange.framework.model.Group.class, cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
	@JoinTable(name = "t_user_group", joinColumns = { @JoinColumn(name = "user_pk") }, inverseJoinColumns = { @JoinColumn(name = "group_pk") })
	private Set<Group> groups = new HashSet<Group>();

	/**
	 * @return Returns the address.
	 */
	public String getAddress() {
		return address;
	}

	/**
	 * @return Returns the description.
	 */
	public String getDescription() {
		return description;
	}

	/**
	 * @return Returns the email.
	 */
	public String getEmail() {
		return email;
	}

	/**
	 * @return Returns the fax.
	 */
	public String getFax() {
		return fax;
	}

	/**
	 * @return Returns the isstop.
	 */
	public boolean isIsstop() {
		return isstop;
	}

	/**
	 * @return Returns the login_no.
	 */
	public String getLogin_no() {
		return login_no;
	}

	/**
	 * @return Returns the login_pwd.
	 */
	public String getLogin_pwd() {
		return login_pwd;
	}

	/**
	 * @return Returns the mobile.
	 */
	public String getMobile() {
		return mobile;
	}

	/**
	 * @return Returns the phone.
	 */
	public String getPhone() {
		return phone;
	}

	/**
	 * @return Returns the user_code.
	 */
	public String getUser_code() {
		return user_code;
	}

	/**
	 * @return Returns the user_name.
	 */
	public String getUser_name() {
		return user_name;
	}

	/**
	 * @param address
	 *            The address to set.
	 */
	public void setAddress(String address) {
		this.address = address;
	}

	/**
	 * @param description
	 *            The description to set.
	 */
	public void setDescription(String description) {
		this.description = description;
	}

	/**
	 * @param email
	 *            The email to set.
	 */
	public void setEmail(String email) {
		this.email = email;
	}

	/**
	 * @param fax
	 *            The fax to set.
	 */
	public void setFax(String fax) {
		this.fax = fax;
	}

	/**
	 * @param isstop
	 *            The isstop to set.
	 */
	public void setIsstop(boolean isstop) {
		this.isstop = isstop;
	}

	/**
	 * @param login_no
	 *            The login_no to set.
	 */
	public void setLogin_no(String login_no) {
		this.login_no = login_no;
	}

	/**
	 * @param login_pwd
	 *            The login_pwd to set.
	 */
	public void setLogin_pwd(String login_pwd) {
		this.login_pwd = login_pwd;
	}

	/**
	 * @param mobile
	 *            The mobile to set.
	 */
	public void setMobile(String mobile) {
		this.mobile = mobile;
	}

	/**
	 * @param phone
	 *            The phone to set.
	 */
	public void setPhone(String phone) {
		this.phone = phone;
	}

	/**
	 * @param user_code
	 *            The user_code to set.
	 */
	public void setUser_code(String user_code) {
		this.user_code = user_code;
	}

	/**
	 * @param user_name
	 *            The user_name to set.
	 */
	public void setUser_name(String user_name) {
		this.user_name = user_name;
	}

	/**
	 * @return Returns the department.
	 */
	public Department getDepartment() {
		return department;
	}

	/**
	 * @param department
	 *            The department to set.
	 */
	public void setDepartment(Department department) {
		this.department = department;
	}

	/**
	 * @return Returns the groups.
	 */
	public Set<Group> getGroups() {
		return groups;
	}

	/**
	 * @param groups
	 *            The groups to set.
	 */
	public void setGroups(Set<Group> groups) {
		this.groups = groups;
	}

	/**
	 * Return true if the user in the special group.
	 * 
	 * @return true if the user in the special group, false otherwise.
	 */
	public boolean inGroup(Group g) {
		if (groups == null || g == null)
			return false;

		for (Iterator iterator = groups.iterator(); iterator.hasNext();) {
			Group group = (Group) iterator.next();
			if (group.getGroup_code().equals(g.getGroup_code()))
				return true;
		}

		return false;
	}

	/**
	 * Return true if the user in the special group.
	 * 
	 * @return true if the user in the special group, false otherwise.
	 */
	public boolean inGroup(String group_code) {
		if (groups == null || group_code == null || group_code.length() <= 0)
			return false;

		for (Iterator iterator = groups.iterator(); iterator.hasNext();) {
			Group group = (Group) iterator.next();
			if (group.getGroup_code().equals(group_code))
				return true;
		}

		return false;
	}

	/**
	 * Return true if the user in the special group.
	 * 
	 * @return true if the user in the special group, false otherwise.
	 */
	public boolean inGroup(Collection gs) {
		if (groups == null || gs == null || gs.size() <= 0)
			return false;

		for (Iterator iterator = gs.iterator(); iterator.hasNext();) {
			Group group = (Group) iterator.next();
			if (inGroup(group))
				return true;
		}

		return false;
	}

	/**
	 * The subordinate department of the user's department which use for data
	 * authority usually
	 */
	// private Collection subordinate;

	/**
	 * @return Returns the subordinate.
	 */
	public Collection searchSubordinate() throws Exception {
		// if (subordinate == null)
		// subordinate =
		return department.getSubordinate();
	}

	/**
	 * @return the homepage
	 */
	public String getHomepage() {
		return homepage;
	}

	/**
	 * @param homepage
	 *            the homepage to set
	 */
	public void setHomepage(String homepage) {
		this.homepage = homepage;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * net.orange.architecture.model.BaseValueObject#satisfy(java.util.Collection
	 * )
	 */
	public boolean satisfy(Collection<String> msg) throws Exception {
		if (msg == null)
			msg = new ArrayList<String>();

		Validator validator = new Validator(msg);

		validator.add(new StringNotNullValidator(getUser_code(), "user code"));
		validator.add(new StringNotNullValidator(getUser_name(), "user name"));
		validator.add(new StringNotNullValidator(getLogin_no(), "login no"));
		validator.add(new StringNotNullValidator(getLogin_pwd(),
				"login password"));
		validator
				.add(new ObjectNotNullValidator(getDepartment(), "department"));
		validator.add(new SetNotNullValidator(getGroups(), "groups"));
		validator.add(new UserCodeFormatValidator(this));
		validator.add(new NotDulicateValidator(this, "user_code", "user code"));
		validator.add(new NotDulicateValidator(this, "login_no", "login no"));

		validator.validate();

		return (msg == null || msg.size() <= 0);
	}
}